/*****************************************************************************************/
/* ECSE 426 - Microprocessor - Fall 2009
/* Final Project
/* lcd.c
/* LCD code
/* Code adapted from code by Michael Bok of www.nighsoft.com
/****************************************************************************************/

#include <msp430x14x.h>
#include <string.h>
#include "lcd.h"
#include "main.h"
#include "uart.h"

//Set pins
#define DB4 0x01
#define DB5 0x02
#define DB6 0x04
#define DB7 0x08

#define RS 0x10
#define RW 0x20
#define E 0x40

//shouldn't need changed
#define LINE_1_ADDRESS 0x00
#define LINE_2_ADDRESS 0x40

//Initialize the LCD

void initLCD(void)
{
  //set pins for output
  P6DIR = 0x00 | DB4 | DB5 | DB6 | DB7 | RS | RW | E;
  
  //set All low (may not be needed)
  P6OUT = 0x00;
    
  //Make RS and RW 0
  P6OUT &= ~RS;
  P6OUT &= ~RW;
  P6OUT &= ~E;
  
  //Pause for the powering of the LCD
  pause();
  pause();
  pause();
  pause();
  
  //Function Set
  sendNibble(0x02);
  sendNibble(0x02);
  sendNibble(0x0F);
  
  //Display On
  sendNibble(0x00);
  sendNibble(0x0F);
  
  //Display Clear
  sendNibble(0x00);
  sendNibble(0x01);
  
  //Entry Mode
  sendNibble(0x00);
  sendNibble(0x06);

  return;
} //End initLCD

// Pause

void pause(void)
{
    volatile unsigned int i;

    i = 5000;
    do 
    {
      i--;
    }
    while (i != 0);  
}//End pause


void pulseE(void)
{
  //set e high
  P6OUT |= E;
  
  //pause
  pause();
  
  //set e low
  P6OUT &= ~E;
  
  //pause
  pause();
}//End pulseE


void sendData(unsigned char data)
{
  //send high part first
  sendNibble((data>>4) & 0x0F);
  sendNibble(data & 0x0F);
}//End sendData


void sendNibble(unsigned char data)
{
  //convert the nibble to the appropriate pins
  if(data & 0x01)
    P6OUT |= DB4;
  else
    P6OUT &= ~DB4;
  
  if(data & 0x02)
    P6OUT |= DB5;
  else
    P6OUT &= ~DB5;
  
  if(data & 0x04)
    P6OUT |= DB6;
  else
    P6OUT &= ~DB6;
  
  if(data & 0x08)
    P6OUT |= DB7;
  else
    P6OUT &= ~DB7;
  
  pulseE();
}//End sendNibble


void testLCD(void)
{
  //move one spot in on top line
  P6OUT &= ~RS;
  P6OUT &= ~RW;
  sendData(0x80 | (LINE_1_ADDRESS + 1));
  
  //Make RS 1 and RW 0
  P6OUT |= RS;
  P6OUT &= ~RW;
  sendData('A');  
  
  //move to bottom line
  P6OUT &= ~RS;
  P6OUT &= ~RW;
  sendData(0x80 | LINE_2_ADDRESS);
  
  //bottom text
  P6OUT |= RS;
  P6OUT &= ~RW;
  sendData('A');
}//End testLCD

void printLCD(char *str)
{
  int i;
  int ctr=0;

  clearLCD();

  P6OUT &= ~RS;
  P6OUT &= ~RW;
  sendData(0x80 | (LINE_1_ADDRESS));
  
  P6OUT |= RS;
  P6OUT &= ~RW;

  for (i=0; i < strlen(str); i++)
  {
    sendData(str[i]);
    if (ctr==23)
    {
      //move to bottom line
      P6OUT &= ~RS;
      P6OUT &= ~RW;
      sendData(0x80 | LINE_2_ADDRESS);
      P6OUT |= RS;
      P6OUT &= ~RW;
    }//End if
    else if (ctr==47)
    {
      ctr=0;
      clearLCD();
      P6OUT &= ~RS;
      P6OUT &= ~RW;
      sendData(0x80 | (LINE_1_ADDRESS));
      P6OUT |= RS;
      P6OUT &= ~RW;
    }//End else if
    ctr++;
  }//End for

  println(str);    // Print line on terminal

} //End of printLCD

void printLCD2(char *str)
{
  int i;
  
  P6OUT &= ~RS;
  P6OUT &= ~RW;
  sendData(0x80 | LINE_2_ADDRESS);

  P6OUT |= RS;
  P6OUT &= ~RW;

  for (i=0; i < strlen(str); i++)
  {
    sendData(str[i]);
  } // End for

  println(str);  // Print line on terminal
}

//Clear the LCD

void clearLCD(void)
{
  //Make RS and RW 0
  P6OUT &= ~RS;
  P6OUT &= ~RW;
  P6OUT &= ~E;

  //Display Clear
  sendNibble(0x00);
  sendNibble(0x01);

  return;
} //End clearLCD
